package main

import (
	"context"
	"fmt"
	"reflect"

	//"google.golang.org/genproto/googleapis/cloud/aiplatform/v1/schema/predict/params"
)

type TestUnit struct {
	FuncName     string
	RequestParam []reflect.Value
	ExpectedResp []reflect.Value
	ActualResp   []reflect.Value
	Check        func() 
}

type TestA struct {
}

func (a *TestA) Func1(ctx context.Context, t *TestB) {
	fmt.Println(ctx, t)
}

func (a *TestA) Func2(ctx context.Context, t1, t2 *TestB) {
	if t1.Name == t2.Name {
		fmt.Println("name is same!")
	}
}

type TestB struct {
	Name string
}



func CallMethods(b interface{}, tus []TestUnit) {
	
	value := reflect.ValueOf(b)
	
	for _, v := range tus {

		method := value.MethodByName(v.FuncName)
		type_ := method.Type() 
		psize := type_.NumIn()

		var params []reflect.Value
		if len(v.RequestParam) > 0 {
			params = v.RequestParam
		} else {
			params := make([]reflect.Value, psize)
			for i := 0 ; i < psize ; i++ {
				//没有指定参数就直接用默认值来填充请求
				params[i] = reflect.Zero(type_.In(i))
				fmt.Printf("%v\n", type_.In(i))
			}
			v.RequestParam = params
		}

		v.ActualResp = method.Call(params)
		v.Check()
	}

}

func BatchCreateTestUnit(symbols []string, f func()) []TestUnit {
	
	uts := []TestUnit{}
	for _, symbol := range symbols {
		uts = append(uts, TestUnit{
			FuncName: symbol,
			Check: f,
		})
	}

	return uts 
}

func CreateTestUnit(symbol string, f func(), params ...interface{}) TestUnit {

	tu := TestUnit{
		FuncName: symbol,
		Check: f,
	}

	for _, p := range params {
		tu.RequestParam = append(tu.RequestParam, reflect.ValueOf(p))	
	}

	return tu
}

func main() {
	a := &TestA{}
	uts := []TestUnit{}

	uts = append(uts, CreateTestUnit("Func2",func() {
			fmt.Println("in check")
		}, context.TODO(), &TestB{Name: "coco"}, &TestB{Name: "coco"}))

	CallMethods(a, uts)
}
